package tool;

import cn.hutool.core.util.ObjectUtil;
import constant.ConfigConstants;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.ColumnConstraints;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.scene.layout.GridPane;
import mapper.generatorMapper;
import org.apache.commons.io.IOUtils;
import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.apache.ibatis.exceptions.PersistenceException;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import util.GenUtils;
import java.io.*;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipOutputStream;

/**
 * 代码生成器
 * Created by Intellij IDEA.
 * User:  老赵
 * Date:  2023/7/6
 */
public class Generator {

    private static SqlSession session;

    private static ComboBox<String> genderComboBox;

    private static TextField driverTextField;

    private static TextField urlTextField;

    private static TextField userNameTextField;

    private static TextField passwordTextField;

    public static void openCodeGeneratorStage() {
        Stage stature = new Stage();
        stature.setTitle("代码生成器");
        stature.setFullScreen(ConfigConstants.FullScreen);

        GridPane gridPane = new GridPane();
        gridPane.setPadding(new Insets(10)); // 设置内边距为10像素
        gridPane.setVgap(10); // 设置垂直间距为10像素
        gridPane.setHgap(10); // 设置水平间距为10像素
        ColumnConstraints columnConstraints = new ColumnConstraints();
        columnConstraints.setPercentWidth(70);
        gridPane.getColumnConstraints().addAll(new ColumnConstraints(), columnConstraints);

        Label driverLabel = new Label("MYSQL驱动器:");
        driverTextField = new TextField();
        driverTextField.setText("com.mysql.jdbc.Driver");
        gridPane.addRow(0,driverLabel,driverTextField);

        Label urlLabel = new Label("MYSQL地址:");
        urlTextField = new TextField();
        urlTextField.setText("jdbc:mysql://localhost:3306/demo");
        gridPane.addRow(1,urlLabel,urlTextField);

        Label userNameLabel = new Label("MYSQL用户名:");
        userNameTextField = new TextField();
        userNameTextField.setText("root");
        gridPane.addRow(2,userNameLabel,userNameTextField);

        Label passwordLabel = new Label("MYSQL密码:");
        passwordTextField = new TextField();
        passwordTextField.setText("root");
        gridPane.addRow(3,passwordLabel,passwordTextField);

        Label chooseTableLabel = new Label("第二步：选择需要生成的表名");
        gridPane.addRow(6,chooseTableLabel);

        genderComboBox = new ComboBox<>();
        gridPane.addRow(7,genderComboBox);
        genderComboBox.setPromptText("选择需要生成的表名");
        genderComboBox.setOnMouseClicked(e -> chooseTableAction());

        Label collectMysqlLabel = new Label("第一步：链接MYSQL");
        gridPane.addRow(4,collectMysqlLabel);

        Button collectionButton = new Button("链接MYSQL");
        gridPane.addRow(5,collectionButton);

        collectionButton.setOnAction(e -> getCollection());

        Label generatorTableLabel = new Label("第三步：代码生成并保存");
        gridPane.addRow(8,generatorTableLabel);
        Button generateButton = new Button("代码生成并保存");
        gridPane.addRow(9,generateButton);
        generateButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                byte[] bytes = onGenerateButtonClicked(genderComboBox.getValue());
                if (null == bytes) {
                    return;
                }
                // 创建一个文件选择器
                FileChooser fileChooser = new FileChooser();
                fileChooser.setTitle("保存文件");
                fileChooser.setInitialFileName("generated_code.zip");
                // 显示保存文件对话框
                File file = fileChooser.showSaveDialog(stature);
                if (file != null) {
                    try (FileOutputStream fos = new FileOutputStream(file)) {
                        // 将字节数组写入文件
                        fos.write(bytes);
                        fos.flush();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        Alert alert = new Alert(Alert.AlertType.INFORMATION);
                        alert.setTitle("信息");
                        alert.setHeaderText(null);
                        alert.setContentText("代码生成成功");
                        alert.showAndWait();
                    }
                }
            }
        });
        Scene scene = new Scene(gridPane, 500, 700);
        stature.setScene(scene);
        stature.show();
    }

    private static void getCollection() {
        try {
            PooledDataSource newDataSource = new PooledDataSource();
            newDataSource.setDriver(driverTextField.getText());
            newDataSource.setUrl(urlTextField.getText());
            newDataSource.setUsername(userNameTextField.getText());
            newDataSource.setPassword(passwordTextField.getText());
            // 创建一个新的 Environment 对象
            Environment newEnvironment = new Environment("newEnvironment", new JdbcTransactionFactory(), newDataSource);
            // 创建一个新的 Configuration 对象
            Configuration newConfiguration = new Configuration(newEnvironment);
            newConfiguration.addMapper(generatorMapper.class);
            // 创建一个新的 SqlSessionFactory
            SqlSessionFactory newSqlSessionFactory = new SqlSessionFactoryBuilder().build(newConfiguration);
            // 使用新的 SqlSessionFactory 获取新的 session
            session = newSqlSessionFactory.openSession();
            Connection connection = session.getConnection();
            Statement statement = connection.createStatement();
            ResultSet resultSet = statement.executeQuery("SELECT 1");
            if (resultSet.next()) {
                driverTextField.setText(driverTextField.getText());
                urlTextField.setText(urlTextField.getText());
                userNameTextField.setText(userNameTextField.getText());
                passwordTextField.setText(passwordTextField.getText());
                //拿到所有的表
                generatorMapper userMapper = session.getMapper(generatorMapper.class);
                List<Map<String, Object>> mapList = userMapper.queryList(null);
                List<String> sortedTableNames = mapList.stream()
                        .map(map -> (String) map.get("tableName"))
                        .sorted(Comparator.comparing(name -> name.substring(0, 1)))
                        .collect(Collectors.toList());
                genderComboBox.getItems().clear();
                genderComboBox.getItems().addAll(sortedTableNames);
                //告知用户链接成功
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setTitle("信息");
                alert.setHeaderText(null);
                alert.setContentText("链接MYSQL成功");
                alert.showAndWait();
            } else {
                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.setTitle("警告");
                alert.setHeaderText(null);
                alert.setContentText("链接MYSQL失败");
                alert.showAndWait();
            }
        } catch (SQLException | PersistenceException e) {
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setTitle("警告");
            alert.setHeaderText(null);
            alert.setContentText("链接MYSQL失败,请检查MYSQL链接配置是否正确");
            alert.showAndWait();
            throw new RuntimeException(e);
        }
    }

    private static void chooseTableAction() {
        if (ObjectUtil.isEmpty(session)) {
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setTitle("警告");
            alert.setHeaderText(null);
            alert.setContentText("请先链接MYSQL");
            alert.showAndWait();
        } else {
            //拿到所有的表
            generatorMapper userMapper = session.getMapper(generatorMapper.class);
            List<Map<String, Object>> mapList = userMapper.queryList(null);
            List<String> sortedTableNames = mapList.stream()
                    .map(map -> (String) map.get("tableName"))
                    .sorted(Comparator.comparing(name -> name.substring(0, 1)))
                    .collect(Collectors.toList());
            genderComboBox.getItems().clear();
            genderComboBox.getItems().addAll(sortedTableNames);
        }
    }

    private static byte[] onGenerateButtonClicked(String table) {
        if (ObjectUtil.isEmpty(session)) {
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setTitle("警告");
            alert.setHeaderText(null);
            alert.setContentText("请先链接MYSQL");
            alert.showAndWait();
            return null;
        }
        if (ObjectUtil.isEmpty(table)) {
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setTitle("警告");
            alert.setHeaderText(null);
            alert.setContentText("请先选择表名");
            alert.showAndWait();
            return null;
        }
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        generatorMapper userMapper = session.getMapper(generatorMapper.class);
        //查询表信息
        Map<String, String> tableName = userMapper.queryTable(table);
        //查询列信息
        List<Map<String, String>> columns = userMapper.queryColumns(table);
        //生成代码
        GenUtils.generatorCode(tableName, columns, zip);
        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }
}
